package com.rabbiter.market.service.sale_management.sale_records.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rabbiter.market.common.redis.service.RedisTemplateService;
import com.rabbiter.market.domain.goods.goods_info.Goods;
import com.rabbiter.market.domain.personnel.employee.Employee;
import com.rabbiter.market.domain.sale.detail_sale_records.DetailSaleRecords;
import com.rabbiter.market.domain.sale.sale_records.SaleRecords;
import com.rabbiter.market.mapper.sale.sale_records.SaleRecordsMapper;
import com.rabbiter.market.qo.sale_records.QuerySaleRecords;
import com.rabbiter.market.service.goods_management.goods.IGoodsService;
import com.rabbiter.market.service.inventory_management.store.IGoodsStoreService;
import com.rabbiter.market.service.member_management.member.IMemberService;
import com.rabbiter.market.service.pay.PayService;
import com.rabbiter.market.service.sale_management.detail_sale_records.IDetailSaleRecordsService;
import com.rabbiter.market.service.sale_management.order.OrderDetailVo;
import com.rabbiter.market.service.sale_management.order.OrderVo;
import com.rabbiter.market.service.sale_management.sale_records.ISaleRecordsService;
import com.rabbiter.market.service.shoppingcart.ShoppingCartService;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

@Service
public class SaleRecordsServiceImpl extends ServiceImpl<SaleRecordsMapper, SaleRecords> implements ISaleRecordsService {

    @Resource
    private IGoodsService goodsService;

    @Resource
    private RedisTemplateService redisTemplateService;

    @Resource
    private IDetailSaleRecordsService detailSaleRecordsService;

    @Resource
    private IGoodsStoreService goodsStoreService;

    @Resource
    private IMemberService memberService;

    @Resource
    private ShoppingCartService shoppingCartService;

    @Resource
    private PayService payService;

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Resource
    private SaleRecordsMapper saleRecordsMapper;

    /**
     * 订单过期时间
     */
    @Value("${alipay.timeout-express}")
    private String timeoutExpress;

    @Override
    public List<Map<String, Object>> getOptionSaleRecordsGoods() {
        QueryWrapper<Goods> wrapper = new QueryWrapper<Goods>().gt("residue_num", 0L);
        List<Goods> list = goodsService.list(wrapper);
        List<Map<String, Object>> goodsList = new ArrayList<>();
        if (list != null && list.size() > 0) {
            for (Goods goods : list) {
                Map<String, Object> map = new HashMap<>();
                map.put("id", goods.getId());
                map.put("name", goods.getName());
                map.put("residueNum", goods.getResidueNum());
                goodsList.add(map);
            }
        }
        return goodsList;
    }

    @Override
    public void saveSaleRecords(SaleRecords saleRecords, String token, HttpServletResponse response) throws Exception {
        // TODO 这里可以先生成订单，再生成二维码，再更新订单的订单号
        // 生成支付二维码
        Map<String, String> alipay = payService.alipay(saleRecords, response);

        if(!"10000".equals(alipay.get("code"))) {
            throw new Exception("二维码获取失败");
        }

        // 订单已存在说明该订单已创建
        SaleRecords records = baseMapper.selectOne(new LambdaQueryWrapper<SaleRecords>().eq(SaleRecords::getCn, saleRecords.getCn()));
        if(ObjectUtils.isNotEmpty(records)) {
            return;
        }

        Employee employee = JSON.parseObject(redisTemplateService.getCacheObject(token), Employee.class);
        saleRecords.setEid(employee.getId());
        saleRecords.setSellTime(new Date());
        saleRecords.setSellby(employee.getNickName());
        saleRecords.setState(SaleRecords.STATE_NORMAL);
        saleRecords.setPayStatus(10);
        saleRecords.setOutTradeNo(alipay.get("out_trade_no"));

        List<Long> shoppingCartIds = new ArrayList<>();
        for (DetailSaleRecords detailSaleRecord : saleRecords.getDetailSaleRecords()) {
            detailSaleRecord.setSellCn(saleRecords.getCn());
            Goods goods = goodsService.getById(detailSaleRecord.getGoodsId());
            UpdateWrapper<Goods> wrapper = new UpdateWrapper<Goods>()
                    .set("sales_volume", goods.getSalesVolume() != null ? goods.getSalesVolume() + detailSaleRecord.getGoodsNum() : detailSaleRecord.getGoodsNum())
                    .set("residue_num", goods.getResidueNum() - detailSaleRecord.getGoodsNum())
                    .eq("id", goods.getId());
            goodsService.update(wrapper);

            if(!Objects.isNull(detailSaleRecord.getShoppingCartId())) {
                shoppingCartIds.add(detailSaleRecord.getShoppingCartId());
            }
        }
        detailSaleRecordsService.saveBatch(saleRecords.getDetailSaleRecords());
        baseMapper.insert(saleRecords);

        // 删除购物车里的数据
        if(!shoppingCartIds.isEmpty()) {
            shoppingCartService.deleteCartGoods(shoppingCartIds);
        }

        //将订单编号发送到队列中
//        System.out.println("将订单编号发送到订单队列中");
//        rabbitTemplate.convertAndSend(
//                RabbitMqConfig.ORDER_EXCHANGE,
//                RabbitMqConfig.ORDER_ROUTING,
//                saleRecords.getCn(),
//                OrderProcessor.messagePostProcessor(String.valueOf(TimeUtil.convertToMilliseconds(timeoutExpress)))
//        );

//        if ("1".equals(saleRecords.getType())) {
//            //为会员增加积分 积分规则：积分=总金额*5%取整
//            String s = saleRecords.getSellTotalmoney() * 0.05 + "";
//            long integral = Long.parseLong(s.split("\\.")[0]);
//            QueryWrapper<Member> memberQueryWrapper = new QueryWrapper<Member>().eq("phone", saleRecords.getMemberPhone());
//            Member member = memberService.getOne(memberQueryWrapper);
//            UpdateWrapper<Member> memberUpdateWrapper = new UpdateWrapper<Member>()
//                    .set("integral", member.getIntegral() != null ? member.getIntegral() +
//                            integral : integral)
//                    .eq("phone", saleRecords.getMemberPhone());
//            memberService.update(memberUpdateWrapper);
//        }
    }

    @Override
    public Page<SaleRecords> queryPageByQoSaleRecords(QuerySaleRecords qo) {
        Page<SaleRecords> page = new Page<>(qo.getCurrentPage(), qo.getPageSize());
        QueryWrapper<SaleRecords> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("state", SaleRecords.STATE_NORMAL);
        queryWrapper.eq(StringUtils.hasText(qo.getType()), "type", qo.getType());
        queryWrapper.likeRight(StringUtils.hasText(qo.getCn()), "cn", qo.getCn());
        queryWrapper.ge(StringUtils.hasText(qo.getStartSellTime()), "sell_time", qo.getStartSellTime());
        queryWrapper.le(StringUtils.hasText(qo.getEndSellTime()), "sell_time", qo.getEndSellTime());
        queryWrapper.eq(StringUtils.hasText(qo.getSellway()), "sellway", qo.getSellway());
        queryWrapper.orderByDesc("sell_time");
        super.page(page, queryWrapper);
        List<SaleRecords> records = page.getRecords();
        if (records != null && records.size() > 0) {
            for (SaleRecords record : records) {
                QueryWrapper<DetailSaleRecords> sellCnWrapper = new QueryWrapper<DetailSaleRecords>().eq("sell_cn", record.getCn());
                List<DetailSaleRecords> list = detailSaleRecordsService.list(sellCnWrapper);
                record.setDetailSaleRecords(list);
            }
        }
        return page;
    }

    @Override
    public List<OrderVo> queryPageByQoSaleRecords(QuerySaleRecords qo, String token) {
        String str = redisTemplateService.getCacheObject(token);
        Employee employee = JSONObject.parseObject(str, Employee.class);

        Page<SaleRecords> page = new Page<>(qo.getCurrentPage(), qo.getPageSize());
        LambdaQueryWrapper<SaleRecords> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SaleRecords::getEid, employee.getId());
        queryWrapper.eq(SaleRecords::getState, SaleRecords.STATE_NORMAL);
        queryWrapper.eq(StringUtils.hasText(qo.getType()), SaleRecords::getType, qo.getType());
        queryWrapper.likeRight(StringUtils.hasText(qo.getCn()), SaleRecords::getCn, qo.getCn());
        queryWrapper.ge(StringUtils.hasText(qo.getStartSellTime()), SaleRecords::getSellTime, qo.getStartSellTime());
        queryWrapper.le(StringUtils.hasText(qo.getEndSellTime()), SaleRecords::getSellTime, qo.getEndSellTime());
        queryWrapper.eq(StringUtils.hasText(qo.getSellway()), SaleRecords::getSellway, qo.getSellway());
        queryWrapper.orderByDesc(SaleRecords::getSellTime);
        super.page(page, queryWrapper);

        List<OrderVo> orderVoList = new ArrayList<>();
        List<SaleRecords> records = page.getRecords();
        if (records != null && !records.isEmpty()) {
            // 获取订单下的所有商品
            for (SaleRecords record : records) {
                OrderVo orderVo = new OrderVo();
                BeanUtils.copyProperties(record, orderVo);
                List<DetailSaleRecords> list = detailSaleRecordsService.list(
                        new LambdaQueryWrapper<DetailSaleRecords>()
                                .eq(DetailSaleRecords::getSellCn, record.getCn())
                );
                List<OrderDetailVo> orderDetailVoList = new ArrayList<>();

                // 获取商品图片
                for (DetailSaleRecords detailSaleRecord : list) {
                    OrderDetailVo orderDetailVo = new OrderDetailVo();
                    BeanUtils.copyProperties(detailSaleRecord, orderDetailVo);
                    LambdaQueryWrapper<Goods> goodsQueryWrapper = new LambdaQueryWrapper<Goods>().eq(Goods::getId, detailSaleRecord.getGoodsId());
                    Goods goods = goodsService.getOne(goodsQueryWrapper);
                    orderDetailVo.setCoverUrl(goods.getCoverUrl());
                    orderDetailVoList.add(orderDetailVo);
                }
                orderVo.setDetailSaleRecords(orderDetailVoList);
                orderVoList.add(orderVo);
            }
        }
        return orderVoList;
    }

    @Override
    public void delSaleRecords(String cn) {
        UpdateWrapper<SaleRecords> wrapper = new UpdateWrapper<>();
        wrapper.eq("cn", cn);
        wrapper.set("state", SaleRecords.STATE_DEL);
        super.update(wrapper);
    }

    @Override
    public void updateSaleRecords(SaleRecords saleRecords) {
        LambdaQueryWrapper<SaleRecords> wrapper = new LambdaQueryWrapper<SaleRecords>()
                .eq(SaleRecords::getCn, saleRecords.getCn());
        baseMapper.update(saleRecords, wrapper);
    }

    @Override
    public SaleRecords getSaleRecordsByOutTradeNo(String outTradeNo) {
        return baseMapper.selectOne(
                new LambdaQueryWrapper<SaleRecords>()
                        .eq(SaleRecords::getOutTradeNo, outTradeNo)
        );
    }

    @Override
    public SaleRecords getOrderByCn(SaleRecords saleRecords) {
        return baseMapper.selectOne(
                new LambdaQueryWrapper<SaleRecords>()
                        .eq(SaleRecords::getCn, saleRecords.getCn())
        );
    }

    @Override
    public List<SaleRecords> getAllOrder() {
        return baseMapper.selectList(
                new LambdaQueryWrapper<SaleRecords>()
                        .eq(SaleRecords::getState, SaleRecords.STATE_NORMAL)
                        .eq(SaleRecords::getPayStatus, 10)
        );
    }

    @Override
    public void updateBatch(List<SaleRecords> updateList, int type) {
        saleRecordsMapper.updateBatch(updateList, type);
    }
}
